package com.justgame.project.cloud.common.util;

import com.justgame.project.cloud.common.constant.Regex;
import com.justgame.project.cloud.base.entity.BaseEntity;
import com.justgame.project.cloud.common.exception.Exc;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 对象工具
 */
public class ObjUtil extends ObjectUtils {

    /**
     * 基础字段自动注入
     */
    public static <T extends BaseEntity> void inject(T source, Boolean isCreator) {
        if (isCreator == null) {
            isCreator = false;
        }
        /* 获取当前人员信息 */
        Long userId = ShiroUtils.getUserIdElseThrow();
        if (isCreator) {
            /* 创建 */
            source.setCreateUser(userId);
            source.setCreateDate(LocalDateTime.now());
        } else {
            /* 更新 */
            source.setUpdateUser(userId);
            source.setUpdateDate(LocalDateTime.now());
        }
        if (Objects.isNull(source.getIsDel())) {
            /* 逻辑删除 */
            source.setIsDel(Boolean.FALSE);
        }
    }


    public static boolean checkId(@Nullable Long id) {
        return id != null && id != -1;
    }

    public static boolean checkId(@Nullable Object obj) {
        if (Objects.nonNull(obj)) {
            try {
                if (obj instanceof BaseEntity) {
                    return checkId(((BaseEntity) obj).getId());
                } else {
                    return checkId(BeanUtils.getProperty(obj, "id"));
                }
            } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                e.printStackTrace();
                return false;
            }
        }
        return false;
    }

    public static boolean isNull(String string) {
        return StringUtils.isBlank(string) || string.equals("null");
    }

    /**
     * 查询当前数据的创建者是否是”我“
     *
     * @param object
     * @param <T>
     * @return
     */
    public static <T extends BaseEntity> boolean isMine(T object) {
        if (object == null || object.getCreateUser() == null) return false;
        Long myId = ShiroUtils.getUserIdElseThrow();
        return object.getCreateUser().equals(myId);
    }

    /**
     * 查询当前数据的创建者是否是”我“
     *
     * @param object
     * @param <T>
     * @return
     */
    public static <T extends BaseEntity> boolean isMine(List<T> object) {
        if (object == null || object.size() == 0) return false;
        Long myId = ShiroUtils.getUserIdElseThrow();
        AtomicBoolean isMine = new AtomicBoolean(true);
        object.forEach(obj -> {
            if (obj.getCreateUser().equals(myId)) {
                isMine.set(false);
            }
        });
        return isMine.get();
    }

    /**
     * remove blank string
     *
     * @return String
     */
    public static String removeBlank(@Nullable String str) {
        String s = "";
        if (str != null) {
            Pattern p = Pattern.compile(Regex.BlankStr);
            Matcher m = p.matcher(str);
            s = m.replaceAll("");
        }
        return s;
    }

    /**
     * remove more all blank string
     *
     * @return String
     */
    public static String removeAllBlank(@Nullable String str) {
        String s = "";
        if (str != null) {
            Pattern p = Pattern.compile("\\s{2,}|\t|\r|\n");
            Matcher m = p.matcher(str);
            s = m.replaceAll(" ");
        }
        return s;
    }

    /**
     * 判断是否是基本类型
     *
     * @param value
     * @return
     */
    public static boolean isBaseType(Object value) {
        return value instanceof String ||
                value instanceof Integer ||
                value instanceof Double ||
                value instanceof Long ||
                value instanceof Float ||
                value instanceof Boolean ||
                value instanceof Byte ||
                value instanceof Character ||
                value instanceof Short;
    }

    public static boolean isExistField(Class<?> clazz,String fieldName){
        return Arrays.stream(clazz.getDeclaredFields()).map(Field::getName).anyMatch(fn -> fn.equals(fieldName));
    }

    public static Exc Exc(String message){
        return new Exc(message);
    }

    public static boolean isPrimitiveWrapper(Class<?> clazz) {
        return clazz == Boolean.class ||
                clazz == Character.class ||
                clazz == Byte.class ||
                clazz == Short.class ||
                clazz == Integer.class ||
                clazz == Long.class ||
                clazz == Float.class ||
                clazz == Double.class;
    }
}
